﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;
using System.Security.Principal;
using System.Web;

namespace Wanet.PublicPortal.Common.Domain
{
	public abstract class BasePersistentItem
	{
		/// <summary>
		/// Gets or sets the ID of the item.
		/// </summary>
		/// <value>The ID of the item.</value>
		public virtual int ID
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the date when the item was created.
		/// </summary>
		/// <value>The date when the item was created.</value>
		public virtual DateTime Created
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the date of the last update.
		/// </summary>
		/// <value>The date of the last update.</value>
		public virtual DateTime LastUpdated
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the date when the item was deleted (in fact its IsActive property was set to false).
		/// No records are deleted physically from the data store.
		/// </summary>
		/// <value>The date when the item was deleted (in fact its IsActive property was set to false).</value>
		public virtual DateTime Deleted
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the created by.
		/// </summary>
		/// <value>The created by.</value>
		public virtual string CreatedBy
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the name who has last updated the item.
		/// </summary>
		/// <value>The name who has last updated the item.</value>
		public virtual string LastUpdatedBy
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is active.
		/// </summary>
		/// <value><c>true</c> if this instance is active; otherwise, <c>false</c>.</value>
		public virtual bool IsActive
		{
			get;
			set;
		}

		/// <summary>
		/// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
		/// <returns>
		/// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
		/// </returns>
		/// <exception cref="T:System.NullReferenceException">
		/// The <paramref name="obj"/> parameter is null.
		/// </exception>
		public override bool Equals(object obj)
		{
			return base.Equals(obj);
		}

		/// <summary>
		/// Serves as a hash function for a particular type.
		/// </summary>
		/// <returns>
		/// A hash code for the current <see cref="T:System.Object"/>.
		/// </returns>
		public override int GetHashCode()
		{
			unchecked
			{
				int hash = ID.GetHashCode();

				return hash * 9 + base.GetHashCode();
			}
		}

		/// <summary>
		/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </returns>
		public override string ToString()
		{
			object value = null;
			Type t = this.GetType();
			PropertyInfo[] props = t.GetProperties();
			StringBuilder result = new StringBuilder();

			result.AppendFormat("{0}************************************************{0}", Environment.NewLine);
			result.AppendFormat("[{0}] details:{1}", t.Name, Environment.NewLine);
			result.AppendFormat("************************************************{0}", Environment.NewLine);

			foreach (PropertyInfo p in props)
			{
				try
				{
					value = p.GetValue(this, null);

					if (value == null)
					{
						value = "null";
					}

					if (value is IList)
					{
						try
						{
							value = string.Format("[{0}]", ((IList)value).Count);
						}
						catch{}
					}
					else if (value is Array)
					{
						try
						{
							value = string.Format("[{0}]", ((Array)value).Length);
						}
						catch{}
					}

					result.AppendFormat("\t{0}: {1}{2}", p.Name, value, Environment.NewLine);
				}
				catch { }
			}

			return result.ToString();
		}

		/// <summary>
		/// Initializes the base object by setting its created and last updated dates to the current date.
		/// Sets base objet to be active by default.
		/// </summary>
		public virtual void InitializeBase()
		{
			string userName = string.Empty;

			if (HttpContext.Current == null)
			{
				userName = WindowsIdentity.GetCurrent().Name;
			}
			else
			{
				userName = HttpContext.Current.User.Identity.Name;
			}

			this.Created = DateTime.Now;
			this.CreatedBy = userName;
			this.IsActive = true;
			this.LastUpdated = DateTime.Now;
			this.LastUpdatedBy = userName;
			this.Deleted = DateTime.Now.GetUnixMinDate();
		}

		/// <summary>
		/// Updates the base object by setting its updated date to the current date.
		/// It doesn't touch any other property of the object.
		/// </summary>
		public virtual void UpdateBase()
		{
			string userName = string.Empty;

			if (HttpContext.Current == null)
			{
				userName = WindowsIdentity.GetCurrent().Name;
			}
			else
			{
				userName = HttpContext.Current.User.Identity.Name;
			}

			this.LastUpdated = DateTime.Now;
			this.LastUpdatedBy = userName;
		}
	}
}
